package cn.pink.gamesrv.human;

import cn.pink.common.support.tools.node.NodeTool;
import cn.pink.common.support.tools.rpc.RpcTool;
import cn.pink.core.*;
import cn.pink.core.entity.EntityProxy;
import cn.pink.core.gen.proxy.DistrClass;
import cn.pink.core.gen.proxy.DistrMethod;
import cn.pink.core.support.Log;
import cn.pink.core.support.Param;
import cn.pink.gamesrv.msg.HumanMsgRoute;
import cn.pink.gatesrv.RPCProxy;
import io.vertx.core.Future;
import lombok.Getter;

import java.util.*;

/**
 * 玩家service
 * 1个玩家对应一个HumanObjectService
 * @Author: pink
 * @Date: 2022/7/6 16:17
 */
@DistrClass(singleton = false, importClass = {CallPoint.class, Param.class})
public class HumanObjectService extends Service {

    /** 协议处理类 */
    private static HumanMsgRoute msgHandler = new HumanMsgRoute();

    /** 玩家对象 */
    @Getter
    private HumanObject humanObj;

    /** 玩家创建的所有entity代理 */
    private final List<EntityProxy> humanEntityList = new ArrayList<>();

    public HumanObjectService(Port port) {
        super(port);
    }

    @Override
    public Object getId() {
        return humanObj.getId();
    }

    @DistrMethod
    public Param defaultHandler(String sessionId, byte[] msgBuf) {
        String currSessionId = (String) humanObj.getSessionPoint().servId;

        if (!currSessionId.equals(sessionId)) {
            Log.game.warn("session not match, sessionId={}, currSessionId={}", sessionId, currSessionId);

            //去gate关闭连接
            RPCProxy.SessionServiceProxy proxy = RPCProxy.SessionServiceProxy.newInstance(port.getCallFromNodeId(), port.getCallFromPortId(), sessionId);
            proxy.closeImmediate();

            return null;
        }

        boolean result = msgHandler.handle(msgBuf, "humanObj", humanObj);

        if (!result) {
            // TODO sendHint
        }

        return null;
    }

    @DistrMethod
    public Param connClosed(String sessionId) {
        String currSessionId = (String) humanObj.getSessionPoint().servId;

        if (!currSessionId.equals(sessionId)) {
            Log.game.warn("session not match, sessionId={}, currSessionId={}", sessionId, currSessionId);
            return null;
        }

        Log.game.info("connClosed: sessionId={}, humanId={}", sessionId, humanObj.getId());

        HumanGlobal.unregister(getPort(), humanObj.getId());

        return null;
    }

    /**
     * 更换sessionPoint
     */
    public void changeSessionPoint(CallPoint sessionPoint) {
        Log.game.info("changeSessionPoint: old={}, new={}", humanObj.getSessionPoint(), sessionPoint);
        humanObj.setSessionPoint(sessionPoint);
    }

    /**
     * 登陆
     */
    public Future<Void> login(CallPoint sessionPoint, String humanId, String userIdentity, String token) {
        // 创建玩家对象
        humanObj = new HumanObject(humanId, sessionPoint, userIdentity, token, this);

        allotDBPoint();

        return humanObj.login();
    }

    /**
     * 分配db处理
     */
    public void allotDBPoint() {
        NodeInfo nodeInfo = NodeTool.getInstance().getRandomNode(NodeType.DB);

        CallPoint point = new CallPoint();
        point.nodeId = nodeInfo.getNodeId();
        point.portId = nodeInfo.getPortId();

        humanObj.setDbPoint(point);
    }

    /**
     * 注册一个实体
     */
    public void regHumanEntity(EntityProxy entity) {
        humanEntityList.add(entity);
    }

    /**
     * 提交所有实体的改动
     */
    public void pulseEntityModifyUpdate() {
        Map<String, String> allUpdate = new HashMap<>();

        // 遍历提交
        for(EntityProxy proxy : humanEntityList) {
            allUpdate.putAll(proxy.getUpdate());

            //清update
            proxy.reset();
        }

        // 执行更新提交
        RpcTool.getInstance().update(String.valueOf(getId()), allUpdate, null, humanObj.getDbPoint());
    }
}
